Surface = require('./cube').Surface if exports?
Cube = require('./cube').Cube if exports?

__runCode = (code, port) ->
	"use strict"
	eval code

class Runtime
	###
	检查当前的架构，是否符合运行的要求
	@blocks 传入一个block 数组，要求是连续的数组
	###
	checkBlocks: (blocks) ->
		@blocks = blocks
		ret = @__checkBlock()
		#TODO
		#@blocks = null

	###
	启动游戏
	@blocks 一个blocks数组
	@callback 每个时钟周期结束后的回掉函数，传回当前电路的情况
	###
	startGame: (blocks, callback) ->
		@blocks = blocks
		@callback = callback
		return false if @__checkBlock() isnt true
		@__startGame()
		return true

	stopGame: () ->
		clearInterval @interval

	__startGame: () ->
		@current_round = 1
		__roundCallback = (that) ->
			#TODO runtime error should be more clear
			#try
				that.__roundCallback()
			#catch block
			#	console.log block
			#	that.__onError block

		@interval = setInterval __roundCallback, 500, @

	__roundCallback: () ->
		console.log "----------------  #{@current_round} started"
		for b in @typologicalSort
			for i in [0..5]
				b.surfaces[i].__runtime_port_value = 0
		for b in @typologicalSort
			evalThis =
				port : (v.__runtime_port_value for v in b.surfaces)
			console.log '---- start run'
			console.log evalThis.port
			if b.type is Cube.type.CODE
				try
					__runCode.call evalThis, b.code
				catch err
					console.log err
					throw b
			else
				b.perform evalThis.port
			console.log evalThis.port
			console.log '---- end run'
			for i in [0..5]
				continue if not evalThis.port[i]?
				value = Math.abs parseInt(evalThis.port[i])
				value = 0 if value is NaN
				surf = b.surfaces[i]
				if surf.info.io is Surface.type.OUT and surf.info.linkTo?
					surf.info.linkTo.__runtime_port_value = value
		data = 
			lightOn : []
			lightOff: []
			move: []
		queue = []
		for b in @typologicalSort
			console.log b.type
			if b.type is Cube.type.LIGHT
				if b.lighting
					data.lightOn.push b
				else
					data.lightOff.push b
			# if b.type is Cube.type.ENGINE
			# 	queue.push b
			# 	data.move.push b
			# 	while queue.length isnt 0
			# 		tmp = queue.shift()
			# 		tmp.direction = b.direction
			# 		for surf in tmp.surfaces
			# 			if surf.info.linkTo? and surf.info.io isnt Surface.type.UNDEFINED and data.move.indexOf(surf.info.linkTo.owner) isnt -1
			# 				queue.push surf.info.linkTo.owner
			# 				data.move.push surf.info.linkTo.owner




		@callback null, @current_round, data
		++@current_round


	__checkBlock: () ->
		# conflict = @__SurfaceLinkConflictCheck()
		# if conflict isnt true
		# 	return conflict

		return @__CubeSortConflictCheck()

	###
	判断面连接的冲突情况
	###
	__SurfaceLinkConflictCheck: () ->
		console.log Surface.type
		for b in @blocks
			for s in b.surfaces
				continue if not s.info.linkTo? or s.info.io is Surface.type.UNDEFINED or s.info.linkTo.info.io is Surface.type.UNDEFINED
				return [s, s.info.linkTo] if s.info.linkTo.info.io + s.info.io isnt 0
		return true

	###
	判断图的拓扑关系冲突情况
	###
	__CubeSortConflictCheck: () ->
		console.log 'start sort'
		for b in @blocks
			b.__runtime_indegree = 0
			for l in b.surfaces
				++b.__runtime_indegree if l.info.linkTo? and l.info.io is Surface.type.IN and l.info.linkTo.info.io is Surface.type.OUT and l.info.linkTo.info.io isnt Surface.type.UNDEFINED

		value = []
		pending = []

		for b in @blocks
			pending.push b if b.__runtime_indegree is 0

		while pending.length isnt 0
			b = pending.shift()
			value.push b
			for l in b.surfaces
				if l.info.linkTo? and l.info.io is Surface.type.OUT and l.info.linkTo.info.io isnt Surface.type.IN and l.info.linkTo.info.io isnt Surface.type.UNDEFINED
					--l.info.linkTo.info.owner.__runtime_indegree 
					if l.info.linkTo.info.owner.__runtime_indegree is 0
						pending.push l.info.linkTo.info.owner

		console.log value
		return false if value.length isnt @blocks.length
		@typologicalSort = value

		output = "typologicalSort value: "
		for b in value
			output += @blocks.indexOf(b) + ', '
		console.log output
		return true

	__onError : (err) ->
		@callback err, @current_round
		@stopGame()

root = window if window?
root = exports if exports?
root.Runtime = Runtime